// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-02-27

package delivery

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/valyala/fasthttp"
	"integration/app/lib/conf"
	"integration/app/lib/wechat"
	"integration/app/models"
	"net/http"
)

var (
	Searcher SearcherManager
)

type (
	// SearcherManager
	// 查询远程订单状态.
	SearcherManager interface {
		Get(ctx context.Context, routine *conf.ErpRoutine, order *models.Order) (res *SearcherResult, err error)
	}

	SearcherResult struct {
		OpenId     string            `json:"openid" label:"付款人"`
		OrderState wechat.OrderState `json:"order_state" label:"订单状态"`
	}

	searcher struct {
	}
)

func (o *searcher) Get(ctx context.Context, routine *conf.ErpRoutine, order *models.Order) (res *SearcherResult, err error) {
	var payload []byte

	// 1. 生成入参.
	if payload, err = json.Marshal(map[string]any{
		"transaction_id":  order.TradeNo,
		"merchant_id":     routine.Merchant,
		"sub_merchant_id": routine.SubMerchant,
	}); err != nil {
		return
	}

	// 2. 查询过程.
	res, err = o.send(ctx, routine, payload, false)
	return
}

func (o *searcher) init() *searcher {
	return o
}

func (o *searcher) send(ctx context.Context, routine *conf.ErpRoutine, payload []byte, refresh bool) (sr *SearcherResult, err error) {
	var (
		request  = fasthttp.AcquireRequest()
		response = fasthttp.AcquireResponse()
		result   = &struct {
			ErrCode any             `json:"errcode"`
			ErrMsg  string          `json:"errmsg"`
			Order   *SearcherResult `json:"order"`
		}{}
		retry = false
		token string
	)

	// 1. 监听结束.
	defer func() {
		fasthttp.ReleaseRequest(request)
		fasthttp.ReleaseResponse(response)

		// 1.2 重试.
		if retry {
			sr, err = o.send(ctx, routine, payload, true)
		}
	}()

	// 1. 获取令牌.
	if refresh {
		token, err = wechat.AccessToken.RefreshToken(ctx, routine)
	} else {
		token, err = wechat.AccessToken.GetToken(ctx, routine)
	}

	// 2. 准备请求.
	request.SetBody(payload)
	request.SetRequestURI(fmt.Sprintf(`https://api.weixin.qq.com/wxa/sec/order/get_order?access_token=%s`, token))
	request.Header.SetMethod(http.MethodPost)
	request.Header.SetContentType("application/json;charset=utf-8")

	// 3. 请求过程.
	if err = fasthttp.Do(request, response); err != nil {
		return
	}
	if status := response.StatusCode(); status != http.StatusOK {
		err = fmt.Errorf(`HTTP %d %s`, status, http.StatusText(status))
		return
	}

	// 4. 解析结果.
	if err = json.Unmarshal(response.Body(), result); err != nil {
		return
	}

	// 4.1 解析成功.
	if result.Order != nil {
		sr = result.Order
		return
	}

	// 4.2 解析失败.
	//     若返回编码为40001允许重试, 防止令牌过期.
	if fmt.Sprintf(`%v`, result.ErrCode) == "40001" && !refresh {
		retry = true
		return
	}

	// 4.3 错误原因.
	err = fmt.Errorf(`%v: %s`, result.ErrCode, result.ErrMsg)
	return
}
